package cn.ym.ymcc.service.impl;

import cn.ym.ymcc.constant.CustomConstant;
import cn.ym.ymcc.doc.CourseDoc;
import cn.ym.ymcc.domain.*;
import cn.ym.ymcc.dto.CourseDetailParamDto;
import cn.ym.ymcc.dto.CourseDto;
import cn.ym.ymcc.dto.CourseInfoDto;
import cn.ym.ymcc.dto.MessageStationDto;
import cn.ym.ymcc.exception.BusinessException;
import cn.ym.ymcc.feign.MediaServerFeign;
import cn.ym.ymcc.feign.SearchServerFeign;
import cn.ym.ymcc.feign.UserFeignClient;
import cn.ym.ymcc.mapper.*;
import cn.ym.ymcc.query.CourseQuery;
import cn.ym.ymcc.result.JSONResult;
import cn.ym.ymcc.result.PageList;
import cn.ym.ymcc.service.ICourseService;
import cn.ym.ymcc.utils.AssertUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.elasticsearch.action.support.ThreadedActionListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 210513347@qq.com
 * @since 2023-05-08
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {

    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private TeacherMapper teacherMapper;
    @Autowired
    private CourseDetailMapper courseDetailMapper;
    @Autowired
    private CourseMarketMapper courseMarketMapper;
    @Autowired
    private CourseResourceMapper courseResourceMapper;
    @Autowired
    private CourseSummaryMapper courseSummaryMapper;
    @Autowired
    private CourseChapterMapper courseChapterMapper;
    @Autowired
    private CourseTypeMapper courseTypeMapper;

    @Autowired
    private SearchServerFeign searchServerFeign;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private JavaMailSender javaMailSender;
    @Autowired
    private UserFeignClient userFeignClient;
    @Autowired
    private MediaServerFeign mediaServerFeign;


    /**
     * 分页+高级
     * @param query
     * @return
     */
    @Override
    public PageList<Course> queryPage(CourseQuery query) {
        Wrapper<Course> wrapper = new EntityWrapper<>();
        if(!StringUtils.isEmpty(query.getKeyword())){
            wrapper.like("name", query.getKeyword());
        }
        Long count = Long.valueOf(courseMapper.selectCount(wrapper));
        if(count==0){
            return new PageList<>();
        }
        List<Course> courses = courseMapper.queryData(query);
        return new PageList<>(count, courses);
    }

    @Override
    @Transactional
    public JSONResult saveCourseDto(CourseDto dto) {
        Course course = dto.getCourse();//课程对象
        CourseDetail courseDetail = dto.getCourseDetail(); //课程详情
        CourseMarket courseMarket = dto.getCourseMarket(); //课程营销
        CourseResource courseResource = dto.getCourseResource(); //课程资源
        List<Long> teacherIds = dto.getTeacherIds(); //老师id
        /**1.校验课程名：不可重复*/
        checkCourseName(course.getName());
        /**2.保存课程表 t_course基本信息*/
        course.setStatus(0);//下线
        course.setLoginId(1L);//todo
        course.setLoginUserName("擎天柱");
        List<Teacher> teachers = teacherMapper.selectBatchIds(teacherIds);
        //追加老师的名字
        String teacherNames = teachers.stream().map(Teacher::getName).collect(Collectors.joining(","));
        course.setTeacherNames(teacherNames);
        courseMapper.insert(course);
        /**3.保存课程详情表 t_course_detail基本信息*/
        courseDetail.setId(course.getId());
        courseDetailMapper.insert(courseDetail);
        /**4.保存课程资源表 t_course_resource基本信息*/
        courseResource.setCourseId(course.getId());
        courseResourceMapper.insert(courseResource);
        /**5.保存课程表和老师表 t_course_teacher的中间关系*/
        courseMapper.saveCourseTeacher(course.getId(), teacherIds);
        /**6.保存课程营销表t_course_market基本信息*/
        courseMarket.setId(course.getId());
        courseMarketMapper.insert(courseMarket);
        /**7.保存课程汇总t_course_summary(初始化数据)*/
        CourseSummary summary = new CourseSummary();
        summary.setId(course.getId());
        summary.setCommentCount(0);
        summary.setSaleCount(0);
        summary.setViewCount(0);
        courseSummaryMapper.insert(summary);
        /**8.修改课程类型t_course_type中的课程数量*/
        CourseType courseType = courseTypeMapper.selectById(course.getCourseTypeId());
        courseType.setTotalCount(courseType.getTotalCount()+1);
        courseTypeMapper.updateById(courseType);
        return JSONResult.success();
    }

    @Override
    public JSONResult updateCourseDto(CourseDto dto) {
        return null;
    }

    /**
     * 校验课程名是否已经被注册
     * @param name
     */
    private void checkCourseName(String name) {
        //wrapper： 封装查询条件用的
        Wrapper<Course> wrapper = new EntityWrapper<>();
        //查询的条件
        wrapper.eq("name", name);
        //根据条件查询实体对象
        Course course = super.selectOne(wrapper);
        AssertUtil.isNull(course,"课程名已注册");
    }


    /**
     * 课程发布的逻辑：
     *      1.校验参数
     *      2.业务校验数据
     *      3.修改课程状态
     *      4.把课程信息同步到es服务中
     *      5.当课程发布成功了之后，我们要给用户发送信息，告诉他我们平台有新课程发布了
     *
     *      哪几类的用户进行推送消息：
     *                      1.VIP用户
     *                      2.收藏了相关类型课程的用户
     *                      3.给注册我们平台的用户都发送(站内信)
     *
     * @param  ids 课程id
     */
    @Override
    public void onLineCourse(Long[] ids, HttpServletRequest request)  {
        //1.从请求头获取login对象，从而获取登陆人对象信息
        //2.根据课程id查询课程对象
        for (Long id : ids) {
            //1.1参数校验，当课程id为空抛出异常
            AssertUtil.isNotNull(id,"参数异常");
            //1.2.根据课程id查询课程对象
            Course course = courseMapper.selectById(id);
            AssertUtil.isNotNull(course,"参数异常");
            if (course.getStatus()==Course.ONLINE){
                throw  new BusinessException("该课程 ["+course.getName()+"] 已上线，请勿重新操作！");
            }
            //1.3:审核 - 百度Ai智能审核
            //3.设置状态为上线状态
            course.setStatus(Course.ONLINE);
            //4.设置上线时间
            course.setOnlineTime(new Date());
            //------------------------------------------------------------------------------
            //5.上线了 创建CourseDoc对象，专门来存储数据，该数据存储到es库中
            CourseDoc courseDoc = new CourseDoc();
            //6.把course里面的数据拷贝到courseDoc中
            BeanUtils.copyProperties(course, courseDoc);
            //6.根据课程id拿到课程营销对象
            CourseMarket market = courseMarketMapper.selectById(id);
            BeanUtils.copyProperties(market, courseDoc);
            courseDoc.setChargeName(market.getCharge()==1?"免费":"收费");
            //7.根据课程id获取课程汇总
            CourseSummary summary = courseSummaryMapper.selectById(id);
            BeanUtils.copyProperties(summary, courseDoc);

            //8.把课程数据同步到es库中
            JSONResult result = searchServerFeign.save(courseDoc);
            //校验远程调用是否成功
            AssertUtil.isTrue(result.isSuccess(), result.getMessage());
            //9.发送站内信
            MessageStationDto messageStationDto = new MessageStationDto();
            messageStationDto.setType("系统消息");
            messageStationDto.setTitle("课程发布");
            String content = "亲爱的用户您好：源码云课堂发布了新课程：%s,请点击<a href='http://localhost:6002/detail.html?id=%s'>%s</a>查看详情";
            content = String.format(content, course.getName(), id, course.getName());
            messageStationDto.setContent(content);
            //todo//要给那些人发
            List<Long> userIds = Arrays.asList(1L, 2L, 3L);

            System.out.println(userIds);
            messageStationDto.setUserIds(userIds);
            //10.mq发送站内信
            SendResult sendResult = rocketMQTemplate.syncSend(CustomConstant.MQ_TOPIC_MESSAGE_STATION + ":"
                    + CustomConstant.MQ_TAGS_MESSAGE_STATION, JSONObject.toJSONString(messageStationDto));
            //发送结果
            AssertUtil.isEquals(sendResult.getSendStatus().toString(), SendStatus.SEND_OK.toString(),"站内信发送失败");
            //11.发送短信通知用户新课程发布了
            //extractedSms(userIds);
            //12.发送邮件通知用户新课程发布了
            //extractedEmail(content, userIds);

            //-------------------------------------------------------------------------------------------
            //5.修改课程状态
            super.updateById(course);
        }

    }

    /**
     * 短信发送
     * @param userIds
     */
    private void extractedSms(List<Long> userIds) {
        List<User> users = userFeignClient.patchQuery(userIds);
        for (User user : users) {
            //SmsUtils.sendSms(user.getPhone(),content);
            System.out.println(user.getPhone()+"  ：发送成功！！！");
        }
    }


    /**发送邮件*/
    private void extractedEmail(String content, List<Long> userIds) {
        try {
            //12.1创建复杂邮件对象
            MimeMessage mimeMessage = javaMailSender.createMimeMessage();
            //12.2发送复杂邮件的工具类
            //true - 能够添加附件
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true,"utf-8");
            //12.3发送方
            helper.setFrom("210513347@qq.com");
            helper.setSubject("系统消息");
            //12.4true - 能够再内容中编写html标签 - 会解析
            helper.setText(content,true);
            List<User> users = userFeignClient.patchQuery(userIds);
            for (User user : users) {
                //3.4收件人
                 helper.setTo(user.getEmail());
                javaMailSender.send(mimeMessage);//发送
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 课程下线
     * @param ids
     * @param request
     */
    @Override
    public void offLineCourse(Long[] ids, HttpServletRequest request) {
        for (Long id : ids) {
            Course course = courseMapper.selectById(id);
            if (course.getStatus()==Course.OFFLINE){
                throw new BusinessException("该宠物 【"+course.getName()+"】 已经是下架过的，请勿重复操作此功能!!!");
            }
            //1.设置状态为下线状态
            course.setStatus(Course.OFFLINE);
            //下线了要把es中的数据删除掉

            //2.修改课程状态
            super.updateById(course);
        }


    }
    /**
     * 根据课程id查询课程详情
     * @param courseId
     * @return
     *          1.参数校验
     *          2.根据课程id查询课程对象
     *          3.业务校验
     *          4.查询课程汇总
     *          5.查询课程详情
     *          6.查询课程营销
     *          7.查询课程对应的所有老师
     *          8.查询课程章节和课程视频
     *
     *
     */
    @Override
    public CourseDetailParamDto detailByCourseId(Long courseId) {
        //1.参数校验（参数不能为空）
        AssertUtil.isNotNull(courseId,"参数错误");
        //2.根据课程id查询课程对象
        Course course = courseMapper.selectById(courseId);
        AssertUtil.isNotNull(course,"参数错误");
        //3.根据课程id查询课程汇总
        CourseSummary courseSummary = courseSummaryMapper.selectById(courseId);
        //4.根据课程id查询课程详情
        CourseDetail courseDetail = courseDetailMapper.selectById(courseId);
        //5.根据课程id查询课程营销
        CourseMarket courseMarket = courseMarketMapper.selectById(courseId);
        //6.根据课程id查询该课程下面所有的老师
        List<Teacher> teachers = teacherMapper.selectListByCourseId(courseId);
        //7.根据课程id查询所有的章节，拿到该课程下面所有的章节
        Wrapper<CourseChapter> wrapper=new EntityWrapper<>();
        wrapper.eq("course_id",courseId);
        List<CourseChapter> courseChapters = courseChapterMapper.selectList(wrapper);
        //8.根据课程id查询该课程下面所有的视频
        JSONResult result = mediaServerFeign.listByCourseId(courseId);
        AssertUtil.isTrue(result.isSuccess(),result.getMessage());
        //9.从result里面拿去视频对象，并转化为List<MediaFile>
        Object data = result.getData();
        List<MediaFile> mediaFiles = JSONObject.parseArray(data.toString(), MediaFile.class);
        //10.把课程章节转为map集合   key:章节id     value:章节对象
        Map<Long, CourseChapter> map = courseChapters.stream().collect(Collectors.toMap(CourseChapter::getId, courseChapter -> courseChapter));
        //11.循环所有的视频
        for (MediaFile mediaFile : mediaFiles) {
            //每个视频对象都能获取到章节id   map.get(视频.get章节id).getMediaFiles().add(循环的视频)
           if ( map.get(mediaFile.getChapterId())!=null){
               map.get(mediaFile.getChapterId()).getMediaFiles().add(mediaFile);
           }
        }
        return new CourseDetailParamDto(course,courseMarket,courseChapters,teachers,courseDetail,courseSummary);
    }
    /**
     * 多个courseId 查询课程详情
     * @param courseId
     * @return
     */
    @Override
    public CourseInfoDto info(String courseId) {
        //1.参数校验
        AssertUtil.isNotEmpty(courseId,"非法请求!!!!");
        //2.把课程id转为数组
        String[] courseIds = courseId.split(",");
        //3.要把string类型数组转化为数组
        List<String> courseIdList = Arrays.stream(courseIds).filter(s -> s.matches(CustomConstant.NUM_REGEX)).collect(Collectors.toList());
        //4.判断课程参数个数
        if(courseIds.length!=courseIdList.size()){
            throw new BusinessException("非法请求");
        }
        //5.根据多个课程id获取多个课程对象
        List<Course> courses = courseMapper.selectBatchIds(courseIdList);
        if(courseIds.length!=courses.size()){
            throw new BusinessException("非法请求");
        }

        //6.定义一个集合，来装CourseDto
        List<CourseDto> courseDtos = new ArrayList<>();
        BigDecimal totalAmount = new BigDecimal("0");
        //7.循环所有的课程
        for (Course course : courses) {
            CourseDto courseDto = new CourseDto();
            //7.1根据课程id查询课程营销对象
            CourseMarket courseMarket = courseMarketMapper.selectById(course.getId());
            //7.2设置课程
            courseDto.setCourse(course);
            //7.3设置课程营销
            courseDto.setCourseMarket(courseMarket);
            //7.4添加金额明细
             totalAmount = totalAmount.add(courseMarket.getPrice());
            //7.5添加课程详情对象
            courseDtos.add(courseDto);
        }
        return new CourseInfoDto(courseDtos,totalAmount);
    }

    /**
     * 课程删除
     * @param id
     * @return
     */
    @Override
    public boolean deleteById(Serializable id) {

//        //2.删除课程详情表 t_course_detail
//        courseDetailMapper.deleteById(id);
//        //3.删除课程资源表 t_course_resource
//        courseResourceMapper.deleteByCourseId((Long) id);
//        //4.删除课程表和老师表 t_course_teacher的中间关系
//        courseTeacherMapper.deleteByCourseId((Long) id);
//        //5.删除课程营销表t_course_market
//        courseMarketMapper.deleteById(id);
//        //6.删除课程汇总t_course_summary
//        courseSummaryMapper.deleteById(id);
//        //7.修改课程类型t_course_type中的课程数量
//
//        //1.删除课程表 t_course
        return super.deleteById(id);
    }






}
